home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / uuencode < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  9.4 KB

  1. Subject:  v07i015:  Uuencode and uudecode
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Mark Horton <cbosgd!mark>
  6. Mod.sources: Volume 7, Issue 15
  7. Archive-name: uuencode
  8.  
  9. [  These programs have been part of the Berkeley distributions for
  10.    quite some time.  Although they have always been in the public
  11.    domain, they have not always been readily available.  I wrote
  12.    the Makefile, and repacked what Mark sent me to include it.
  13.    --r$  ]
  14.  
  15. #!/bin/sh
  16. # This is a shell archive.  Remove anything before this line,
  17. # then unpack it by saving it in a file and typing "sh file".
  18.  
  19. # Exit status; set to 1 on "wc" errors or if would overwrite.
  20. STATUS=0
  21. # Contents:  Makefile uuencode.1 uudecode.c uuencode.c
  22.  
  23. echo x - Makefile
  24. if test -f Makefile ; then
  25.     echo Makefile exists, putting output in $$Makefile
  26.     OUT=$$Makefile
  27.     STATUS=1
  28. else
  29.     OUT=Makefile
  30. fi
  31. sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
  32. XXCFLAGS    = -O
  33.  
  34. XXall:    uuencode uudecode
  35. XXinstall:    all
  36. XX    cp uuencode uudecode /usr/bin
  37. XX    strip /usr/bin/uuencode
  38. XX    strip /usr/bin/uudecode
  39. XX    cp uuencode.1 /usr/man/man1/uuencode.1
  40.  
  41. XXuuencode:    uuencode.c    ;    cc -o $@ $(CFLAGS) $?
  42. XXuudecode:    uudecode.c    ;    cc -o $@ $(CFLAGS) $?
  43. @//E*O*F Makefile//
  44. chmod u=rw,g=rw,o=rw $OUT
  45.  
  46. echo x - uuencode.1
  47. if test -f uuencode.1 ; then
  48.     echo uuencode.1 exists, putting output in $$uuencode.1
  49.     OUT=$$uuencode.1
  50.     STATUS=1
  51. else
  52.     OUT=uuencode.1
  53. fi
  54. sed 's/^XX//' > $OUT <<'@//E*O*F uuencode.1//'
  55. XX.TH UUENCODE 1 "1 June 1980"
  56. XX.UC 4
  57. XX.SH NAME
  58. XXuuencode,uudecode \- encode/decode a binary file for transmission via mail
  59. XX.SH SYNOPSIS
  60. XX.B uuencode
  61. XX[ source ] remotedest |
  62. XX.B mail
  63. XXsys1!sys2!..!decode
  64. XX.br
  65. XX.B uudecode
  66. XX[ file ]
  67. XX.SH DESCRIPTION
  68. XX.I Uuencode
  69. XXand
  70. XX.I uudecode
  71. XXare used to send a binary file via uucp (or other) mail.
  72. XXThis combination can be used over indirect mail links
  73. XXeven when
  74. XX.IR uusend (1C)
  75. XXis not available.
  76. XX.PP
  77. XX.I Uuencode
  78. XXtakes the named source file (default standard input) and
  79. XXproduces an encoded version on the standard output.
  80. XXThe encoding uses only printing ASCII characters,
  81. XXand includes the mode of the file and the
  82. XX.I remotedest
  83. XXfor recreation on the remote system.
  84. XX.PP
  85. XX.I Uudecode
  86. XXreads an encoded file,
  87. XXstrips off any leading and trailing lines added by mailers,
  88. XXand recreates the original file with the specified mode and name.
  89. XX.PP
  90. XXThe intent is that all mail to the user ``decode'' should be filtered
  91. XXthrough the uudecode program.  This way the file is created automatically
  92. XXwithout human intervention.
  93. XXThis is possible on the uucp network by either using
  94. XX.I sendmail
  95. XXor by making
  96. XX.I rmail
  97. XXbe a link to
  98. XX.I Mail
  99. XXinstead of
  100. XX.I mail.
  101. XXIn each case, an alias must be created in a master file to get
  102. XXthe automatic invocation of uudecode.
  103. XX.PP
  104. XXIf these facilities are not available, the file can be sent to a
  105. XXuser on the remote machine who can uudecode it manually.
  106. XX.PP
  107. XXThe encode file has an ordinary text form and can be edited
  108. XXby any text editor to change the mode or remote name.
  109. XX.SH SEE\ ALSO
  110. XXuuencode(5), uusend(1C), uucp(1C), uux(1C), mail(1)
  111. XX.SH AUTHOR
  112. XXMark Horton
  113. XX.SH BUGS
  114. XXThe file is expanded by 35% (3 bytes become 4 plus control information)
  115. XXcausing it to take longer to transmit.
  116. XX.PP
  117. XXThe user on the remote system who is invoking
  118. XX.I uudecode
  119. XX(often
  120. XX.I uucp)
  121. XXmust have write permission on the specified file.
  122. @//E*O*F uuencode.1//
  123. chmod u=rw,g=r,o=r $OUT
  124.  
  125. echo x - uudecode.c
  126. if test -f uudecode.c ; then
  127.     echo uudecode.c exists, putting output in $$uudecode.c
  128.     OUT=$$uudecode.c
  129.     STATUS=1
  130. else
  131.     OUT=uudecode.c
  132. fi
  133. sed 's/^XX//' > $OUT <<'@//E*O*F uudecode.c//'
  134. XX/*
  135. XX * uudecode [input]
  136. XX *
  137. XX * create the specified file, decoding as you go.
  138. XX * used with uuencode.
  139. XX */
  140. XX#include <stdio.h>
  141. XX#include <pwd.h>
  142. XX#include <sys/types.h>
  143. XX#include <sys/stat.h>
  144.  
  145. XX/* single character decode */
  146. XX#define DEC(c)    (((c) - ' ') & 077)
  147.  
  148. XXmain(argc, argv)
  149. XXchar **argv;
  150. XX{
  151. XX    FILE *in, *out;
  152. XX    struct stat sbuf;
  153. XX    int mode;
  154. XX    char dest[128];
  155. XX    char buf[80];
  156.  
  157. XX    /* optional input arg */
  158. XX    if (argc > 1) {
  159. XX        if ((in = fopen(argv[1], "r")) == NULL) {
  160. XX            perror(argv[1]);
  161. XX            exit(1);
  162. XX        }
  163. XX        argv++; argc--;
  164. XX    } else
  165. XX        in = stdin;
  166.  
  167. XX    if (argc != 1) {
  168. XX        printf("Usage: uudecode [infile]\n");
  169. XX        exit(2);
  170. XX    }
  171.  
  172. XX    /* search for header line */
  173. XX    for (;;) {
  174. XX        if (fgets(buf, sizeof buf, in) == NULL) {
  175. XX            fprintf(stderr, "No begin line\n");
  176. XX            exit(3);
  177. XX        }
  178. XX        if (strncmp(buf, "begin ", 6) == 0)
  179. XX            break;
  180. XX    }
  181. XX    sscanf(buf, "begin %o %s", &mode, dest);
  182.  
  183. XX    /* handle ~user/file format */
  184. XX    if (dest[0] == '~') {
  185. XX        char *sl;
  186. XX        struct passwd *getpwnam();
  187. XX        char *index();
  188. XX        struct passwd *user;
  189. XX        char dnbuf[100];
  190.  
  191. XX        sl = index(dest, '/');
  192. XX        if (sl == NULL) {
  193. XX            fprintf(stderr, "Illegal ~user\n");
  194. XX            exit(3);
  195. XX        }
  196. XX        *sl++ = 0;
  197. XX        user = getpwnam(dest+1);
  198. XX        if (user == NULL) {
  199. XX            fprintf(stderr, "No such user as %s\n", dest);
  200. XX            exit(4);
  201. XX        }
  202. XX        strcpy(dnbuf, user->pw_dir);
  203. XX        strcat(dnbuf, "/");
  204. XX        strcat(dnbuf, sl);
  205. XX        strcpy(dest, dnbuf);
  206. XX    }
  207.  
  208. XX    /* create output file */
  209. XX    out = fopen(dest, "w");
  210. XX    if (out == NULL) {
  211. XX        perror(dest);
  212. XX        exit(4);
  213. XX    }
  214. XX    chmod(dest, mode);
  215.  
  216. XX    decode(in, out);
  217.  
  218. XX    if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  219. XX        fprintf(stderr, "No end line\n");
  220. XX        exit(5);
  221. XX    }
  222. XX    exit(0);
  223. XX}
  224.  
  225. XX/*
  226. XX * copy from in to out, decoding as you go along.
  227. XX */
  228. XXdecode(in, out)
  229. XXFILE *in;
  230. XXFILE *out;
  231. XX{
  232. XX    char buf[80];
  233. XX    char *bp;
  234. XX    int n;
  235.  
  236. XX    for (;;) {
  237. XX        /* for each input line */
  238. XX        if (fgets(buf, sizeof buf, in) == NULL) {
  239. XX            printf("Short file\n");
  240. XX            exit(10);
  241. XX        }
  242. XX        n = DEC(buf[0]);
  243. XX        if (n <= 0)
  244. XX            break;
  245.  
  246. XX        bp = &buf[1];
  247. XX        while (n > 0) {
  248. XX            outdec(bp, out, n);
  249. XX            bp += 4;
  250. XX            n -= 3;
  251. XX        }
  252. XX    }
  253. XX}
  254.  
  255. XX/*
  256. XX * output a group of 3 bytes (4 input characters).
  257. XX * the input chars are pointed to by p, they are to
  258. XX * be output to file f.  n is used to tell us not to
  259. XX * output all of them at the end of the file.
  260. XX */
  261. XXoutdec(p, f, n)
  262. XXchar *p;
  263. XXFILE *f;
  264. XX{
  265. XX    int c1, c2, c3;
  266.  
  267. XX    c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  268. XX    c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  269. XX    c3 = DEC(p[2]) << 6 | DEC(p[3]);
  270. XX    if (n >= 1)
  271. XX        putc(c1, f);
  272. XX    if (n >= 2)
  273. XX        putc(c2, f);
  274. XX    if (n >= 3)
  275. XX        putc(c3, f);
  276. XX}
  277.  
  278.  
  279. XX/* fr: like read but stdio */
  280. XXint
  281. XXfr(fd, buf, cnt)
  282. XXFILE *fd;
  283. XXchar *buf;
  284. XXint cnt;
  285. XX{
  286. XX    int c, i;
  287.  
  288. XX    for (i=0; i<cnt; i++) {
  289. XX        c = getc(fd);
  290. XX        if (c == EOF)
  291. XX            return(i);
  292. XX        buf[i] = c;
  293. XX    }
  294. XX    return (cnt);
  295. XX}
  296.  
  297. XX/*
  298. XX * Return the ptr in sp at which the character c appears;
  299. XX * NULL if not found
  300. XX */
  301.  
  302. XX#define    NULL    0
  303.  
  304. XXchar *
  305. XXindex(sp, c)
  306. XXregister char *sp, c;
  307. XX{
  308. XX    do {
  309. XX        if (*sp == c)
  310. XX            return(sp);
  311. XX    } while (*sp++);
  312. XX    return(NULL);
  313. XX}
  314. @//E*O*F uudecode.c//
  315. chmod u=rw,g=r,o=r $OUT
  316.  
  317. echo x - uuencode.c
  318. if test -f uuencode.c ; then
  319.     echo uuencode.c exists, putting output in $$uuencode.c
  320.     OUT=$$uuencode.c
  321.     STATUS=1
  322. else
  323.     OUT=uuencode.c
  324. fi
  325. sed 's/^XX//' > $OUT <<'@//E*O*F uuencode.c//'
  326. XX/*
  327. XX * uuencode [input] output
  328. XX *
  329. XX * Encode a file so it can be mailed to a remote system.
  330. XX */
  331. XX#include <stdio.h>
  332. XX#include <sys/types.h>
  333. XX#include <sys/stat.h>
  334.  
  335. XX/* ENC is the basic 1 character encoding function to make a char printing */
  336. XX#define ENC(c) (((c) & 077) + ' ')
  337.  
  338. XXmain(argc, argv)
  339. XXchar **argv;
  340. XX{
  341. XX    FILE *in;
  342. XX    struct stat sbuf;
  343. XX    int mode;
  344.  
  345. XX    /* optional 1st argument */
  346. XX    if (argc > 2) {
  347. XX        if ((in = fopen(argv[1], "r")) == NULL) {
  348. XX            perror(argv[1]);
  349. XX            exit(1);
  350. XX        }
  351. XX        argv++; argc--;
  352. XX    } else
  353. XX        in = stdin;
  354.  
  355. XX    if (argc != 2) {
  356. XX        printf("Usage: uuencode [infile] remotefile\n");
  357. XX        exit(2);
  358. XX    }
  359.  
  360. XX    /* figure out the input file mode */
  361. XX    fstat(fileno(in), &sbuf);
  362. XX    mode = sbuf.st_mode & 0777;
  363. XX    printf("begin %o %s\n", mode, argv[1]);
  364.  
  365. XX    encode(in, stdout);
  366.  
  367. XX    printf("end\n");
  368. XX    exit(0);
  369. XX}
  370.  
  371. XX/*
  372. XX * copy from in to out, encoding as you go along.
  373. XX */
  374. XXencode(in, out)
  375. XXFILE *in;
  376. XXFILE *out;
  377. XX{
  378. XX    char buf[80];
  379. XX    int i, n;
  380.  
  381. XX    for (;;) {
  382. XX        /* 1 (up to) 45 character line */
  383. XX        n = fr(in, buf, 45);
  384. XX        putc(ENC(n), out);
  385.  
  386. XX        for (i=0; i<n; i += 3)
  387. XX            outdec(&buf[i], out);
  388.  
  389. XX        putc('\n', out);
  390. XX        if (n <= 0)
  391. XX            break;
  392. XX    }
  393. XX}
  394.  
  395. XX/*
  396. XX * output one group of 3 bytes, pointed at by p, on file f.
  397. XX */
  398. XXoutdec(p, f)
  399. XXchar *p;
  400. XXFILE *f;
  401. XX{
  402. XX    int c1, c2, c3, c4;
  403.  
  404. XX    c1 = *p >> 2;
  405. XX    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  406. XX    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  407. XX    c4 = p[2] & 077;
  408. XX    putc(ENC(c1), f);
  409. XX    putc(ENC(c2), f);
  410. XX    putc(ENC(c3), f);
  411. XX    putc(ENC(c4), f);
  412. XX}
  413.  
  414. XX/* fr: like read but stdio */
  415. XXint
  416. XXfr(fd, buf, cnt)
  417. XXFILE *fd;
  418. XXchar *buf;
  419. XXint cnt;
  420. XX{
  421. XX    int c, i;
  422.  
  423. XX    for (i=0; i<cnt; i++) {
  424. XX        c = getc(fd);
  425. XX        if (c == EOF)
  426. XX            return(i);
  427. XX        buf[i] = c;
  428. XX    }
  429. XX    return (cnt);
  430. XX}
  431. @//E*O*F uuencode.c//
  432. chmod u=rw,g=r,o=r $OUT
  433.  
  434. echo Inspecting for damage in transit...
  435. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  436. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  437. cat > $temp <<\!!!
  438.       11      35     261 Makefile
  439.       67     325    1839 uuencode.1
  440.      180     502    2865 uudecode.c
  441.      105     299    1623 uuencode.c
  442.      363    1161    6588 total
  443. !!!
  444. wc  Makefile uuencode.1 uudecode.c uuencode.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  445. if test -s $dtemp ; then
  446.     echo "Ouch [diff of wc output]:"
  447.     cat $dtemp
  448.     STATUS=1
  449. elif test $STATUS = 0 ; then
  450.     echo "No problems found."
  451. else
  452.     echo "WARNING -- PROBLEMS WERE FOUND..."
  453. fi
  454. exit $STATUS
  455.